<script
	lang="ts"
	setup
	generic="
		T extends {
			[key: string]: any;
		}
	"
>
import { defineComponent, ref, toRaw } from "vue";
import { Rule } from "ant-design-vue/es/form";
import { CloseCircleOutlined } from "@ant-design/icons-vue";
import { langCN } from "@/lang/zh-cn";
import { AntdColumsType, TreeOptionType } from "#/antd-vue";

const props = withDefaults(
	defineProps<{
		form: T;
		formColums: AntdColumsType<T>[];
		rules?: Record<keyof T, Rule[]>;
		formSubmit?: () => void;
	}>(),
	{},
);

const form = defineModel<T>("form");

const VNodes = defineComponent({
	props: {
		vnodes: {
			type: Object,
			required: true,
		},
	},
	render() {
		return this.vnodes;
	},
});

const formRef = ref();

// 表单提交
const onSubmit = () => {
	formRef.value
		.validate()
		.then(() => {
			console.log("values", form.value, toRaw(form.value));
			props.formSubmit && props.formSubmit();
		})
		.catch((error: Error) => {
			console.log("error", error);
		});
};

// 重置表单
const resetForm = () => {
	formRef.value.resetFields();
};

// 表单验证
const validateField = (fieldName: keyof T) => {
	if (formRef.value) {
		formRef.value.validateFields(fieldName, (errors?: any) => {
			if (errors) {
				console.error("Field validation failed:", errors);
			} else {
				console.log("Field validation passed");
			}
		});
	}
};

interface TreeDataType {
	len: number;
	options: TreeOptionType[];
}

// 递归 获取所有子集长度
function loopfn(options: TreeOptionType[], data: TreeDataType) {
	options.forEach((item) => {
		if (item.children && item.children?.length > 0) {
			loopfn(item.children, data);
		} else {
			data.len += 1;
			data.options.push(item);
		}
	});
}

// select 全选/全部选s
const handleSelectAll = (name: keyof T, options: TreeOptionType[] | undefined) => {
	if (form.value && Array.isArray(form.value[name]) && options?.length) {
		const data: TreeDataType = {
			len: 0,
			options: [],
		};

		loopfn(options, data);

		// 判断是否全选
		if (form.value[name].length === data.len) {
			(form.value[name] as any) = [];
		} else {
			(form.value[name] as any) = data.options.map((item) => item.value);
		}

		// 全选 / 全不选  按钮不会出发表单验证，需要主动触发表单验证
		validateField(name);
	}
};
</script>

<template>
	<!-- props.formColums.some((item) => item.label)  不存在label说明是筛选框模式 -->
	<a-form
		ref="formRef"
		:model="form"
		:rules="props?.rules"
		:class="props.formColums.some((item) => item.label) ? '' : 'inline-flex gap-10'"
	>
		<template v-for="item in props.formColums" :key="JSON.stringify(item)">
			<!-- input输入框 -->
			<a-form-item :label="item.label" :name="item.name">
				<a-tooltip :placement="item.payload?.placement">
					<template #title v-if="item.tooltip?.title">{{ item.tooltip?.title }}</template>
					<a-input
						v-if="item.type === 'input' && item.name && form?.hasOwnProperty(item.name)"
						v-model:value="form[item.name]"
						:type="item.payload?.type ?? 'text'"
						:class="[item.payload?.className ?? '', 'formPublicStyle']"
						:size="item.payload?.size ?? 'middle'"
						:placeholder="item.payload?.placeholder"
						:allowClear="item.payload?.allowClear ?? true"
					>
						<template #clearIcon>
							<CloseCircleOutlined />
						</template>
					</a-input>

					<!-- select选择器 -->
					<a-select
						v-if="item.type === 'select' && item.name && form?.hasOwnProperty(item.name)"
						v-model:value="form[item.name]"
						:class="[item.payload?.className ?? '', 'formPublicStyle']"
						:size="item.payload?.size"
						:placeholder="item.payload?.placeholder"
						:allowClear="item.payload?.allowClear ?? true"
						:mode="item.payload?.mode"
						:maxTagCount="item.payload?.maxTagCount ?? 1"
						:maxTagTextLength="item.payload?.maxTagTextLength ?? 2"
					>
						<template #clearIcon>
							<CloseCircleOutlined />
						</template>
						<template v-if="item.payload?.options">
							<template v-for="option in item.payload?.options" :key="option.value">
								<a-select-opt-group v-if="option.children" :value="option.value">
									<template #label>
										<component :is="option.icon" />
										{{ option.label }}
									</template>
									<template v-if="option.children">
										<a-select-option
											v-for="child in option.children"
											:value="child.value"
											:key="child.id ?? child.value"
										>
											{{ child.label }}
										</a-select-option>
									</template>
								</a-select-opt-group>
								<a-select-option v-else :value="option.value">
									{{ option.label }}
								</a-select-option>
							</template>
						</template>
						<template v-if="item.payload?.mode === 'multiple'" #dropdownRender="{ menuNode: menu }">
							<a-button
								type="text"
								class="w-100% text-center"
								@click="handleSelectAll(item.name, item.payload?.options)"
							>
								全选 / 全不选
							</a-button>
							<v-nodes :vnodes="menu" />
						</template>
					</a-select>

					<!-- switch开关 -->
					<a-switch
						v-if="item.type === 'switch' && item.name && form?.hasOwnProperty(item.name)"
						v-model:checked="form[item.name]"
						:class="item.payload?.className"
						:size="item.payload?.size"
					/>

					<!-- Segmented 分段控制器 -->
					<a-segmented
						v-if="item.type === 'segmented' && item.name && form?.hasOwnProperty(item.name)"
						v-model:value="form[item.name]"
						:class="item.payload?.className"
						:size="item.payload?.size"
						:options="item.payload?.options"
					>
						<!-- <template #label="{ value: val, payload = {} }"> -->
						<template #label>
							<div class="p-4">
								<!-- <template v-if="payload.icon">
									<a-avatar :src="payload.src" :style="payload.style">
										<template #icon><component :is="payload.icon" /></template>
										{{ payload.content }}
									</a-avatar>
								</template>
								<template v-else>
									<a-avatar :src="payload.src" :style="payload.style">
										{{ payload.content }}
									</a-avatar>
								</template> -->
								<div>{{ item.label }}</div>
							</div>
						</template>
					</a-segmented>

					<!-- checkbox 多选框 -->
					<a-checkbox-group
						v-if="item.type === 'checkbox' && item.name && form?.hasOwnProperty(item.name)"
						v-model:value="form[item.name]"
					>
						<a-checkbox
							v-for="(option, index) in item.payload?.options"
							:key="option?.id ?? index"
							:value="option.value"
						>
							{{ option.label }}
						</a-checkbox>
					</a-checkbox-group>

					<!-- radio 单选框 -->
					<a-radio-group
						v-if="item.type === 'radio' && item.name && form?.hasOwnProperty(item.name)"
						v-model:value="form[item.name]"
					>
						<a-radio
							v-for="(option, index) in item.payload?.options"
							:key="option?.id ?? index"
							:value="option.value"
						>
							{{ option.label }}
						</a-radio>
					</a-radio-group>

					<!-- 文本域 textarea -->
					<a-textarea
						v-if="item.type === 'textarea' && item.name && form?.hasOwnProperty(item.name)"
						v-model:value="form[item.name]"
						:class="item.payload?.className"
						:placeholder="item.payload?.placeholder"
						:showCount="item.payload?.showCount"
						:allowClear="item.payload?.allowClear ?? true"
					>
						<template #clearIcon>
							<CloseCircleOutlined />
						</template>
					</a-textarea>

					<!-- cascader 级联选择器 -->
					<a-cascader
						v-if="item.type === 'cascader' && item.name && form?.hasOwnProperty(item.name)"
						v-model:value="form[item.name]"
						:class="item.payload?.className"
						:placeholder="item.payload?.placeholder"
						:allowClear="item.payload?.allowClear ?? true"
						:changeOnSelect="true"
						:expandTrigger="item.payload?.expandTrigger ?? 'hover'"
						:options="item.payload?.options"
						:maxTagCount="item.payload?.maxTagCount ?? 1"
						:multiple="item.payload?.multiple"
					>
						<template #clearIcon> <CloseCircleOutlined /> </template>
					</a-cascader>

					<!-- 提交 -->
					<a-form-item v-if="item.type === 'button'">
						<a-button type="primary" @click="onSubmit">{{ langCN.opration.submit }}</a-button>
						<a-button style="margin-left: 10px" @click="resetForm">{{ langCN.opration.reset }}</a-button>
					</a-form-item>
				</a-tooltip>
			</a-form-item>
		</template>
	</a-form>
</template>

<style scoped>
.ant-select-selection-item-content {
	white-space: nowrap; /* 不换行 */
	overflow: hidden; /* 溢出隐藏 */
	text-overflow: ellipsis; /* 超出部分用省略号表示 */
	max-width: 4rem; /* 最大宽度，根据需要调整 */
}

/* form 表单的公共配置 */
.formPublicStyle {
	width: 160px;
}
</style>
